package com.itxuhang.spring.factory;

import com.itxuhang.spring.po.BeanDefinition;
import com.itxuhang.spring.registry.SingletonBeanRegistry;

/**
 * 该类主要负责去制定getBean的流程，至于创建Bean或者获取BeanDefinition的细节，该类不负责
 */
public abstract class AbstractBeanFactory extends SingletonBeanRegistry implements ListableBeanFactory {

    @Override
    public Object getBean(String beanName) {
        // 1.在单例Bean的集合中查找指定beanName的Bean实例是否存在
        Object bean = this.getSingleton(beanName);
        // 2.如果存在则直接返回
        if (bean != null) {
            return bean;
        }
        // 3.如果不存在，则根据beanName去BeanDefinition集合中查找对应的BeanDefinition
        BeanDefinition bd = getBeanDefinition(beanName);
        if (bd == null){
            return null;
        }
        // 4.判断该Bean是单例还是多例
        if (bd.isSingleton()){
            // 创建Bean实例，并且完成相应的属性初始化操作和初始化方法的调用
            bean = createBean(bd);
            // 5.如果是单例Bean，则将创建出来的Bean实例，放入单例Bean集合
            this.addSingleton(beanName,bean);
        }else if (bd.isPrototype()){
            // 6.如果是多例Bean，则直接将创建出来的Bean实例返回
            bean = createBean(bd);
        }else{

        }

        return bean;
    }

    // BeanDefinition的获取，也有多种方式，比如XML中获取，还有注解中获取等
    // 所以AbstractBeanFactory就不去具体实现BeanDefinition的获取了
    protected abstract BeanDefinition getBeanDefinition(String beanName);

    // 具体创建Bean对象的方式，比较复杂，而且方式也不唯一，这个事情，AbstractBeanFactory就不去操心了
    // 通过[抽象模板方法设计模式]，将createBean的实现延迟到子类
    protected abstract Object createBean(BeanDefinition bd) ;
}
